home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 4: GNU Archives / Linux Cubed Series 4 - GNU Archives.iso / gnu / glibc-1.09 / glibc-1 / glibc-1.09.1 / sunrpc / rpcinfo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-18  |  16.2 KB  |  666 lines

  1. /* @(#)rpcinfo.c    2.2 88/08/11 4.0 RPCSRC */
  2. #ifndef lint
  3. static    char sccsid[] = "@(#)rpcinfo.c 1.22 87/08/12 SMI";
  4. #endif
  5.  
  6. /*
  7.  * Copyright (C) 1986, Sun Microsystems, Inc.
  8.  */
  9.  
  10. /*
  11.  * rpcinfo: ping a particular rpc program
  12.  *     or dump the portmapper
  13.  */
  14.  
  15. /*
  16.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  17.  * unrestricted use provided that this legend is included on all tape
  18.  * media and as a part of the software program in whole or part.  Users
  19.  * may copy or modify Sun RPC without charge, but are not authorized
  20.  * to license or distribute it to anyone else except as part of a product or
  21.  * program developed by the user.
  22.  * 
  23.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  24.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  25.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  26.  * 
  27.  * Sun RPC is provided with no support and without any obligation on the
  28.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  29.  * modification or enhancement.
  30.  * 
  31.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  32.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  33.  * OR ANY PART THEREOF.
  34.  * 
  35.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  36.  * or profits or other special, indirect and consequential damages, even if
  37.  * Sun has been advised of the possibility of such damages.
  38.  * 
  39.  * Sun Microsystems, Inc.
  40.  * 2550 Garcia Avenue
  41.  * Mountain View, California  94043
  42.  */
  43.  
  44. #include <rpc/rpc.h>
  45. #include <stdio.h>
  46. #include <sys/socket.h>
  47. #include <netdb.h>
  48. #include <rpc/pmap_prot.h>
  49. #include <rpc/pmap_clnt.h>
  50. #include <signal.h>
  51. #include <ctype.h>
  52.  
  53. #define MAXHOSTLEN 256
  54.  
  55. #define    MIN_VERS    ((u_long) 0)
  56. #define    MAX_VERS    ((u_long) 4294967295L)
  57.  
  58. static void    udpping(/*u_short portflag, int argc, char **argv*/);
  59. static void    tcpping(/*u_short portflag, int argc, char **argv*/);
  60. static int    pstatus(/*CLIENT *client, u_long prognum, u_long vers*/);
  61. static void    pmapdump(/*int argc, char **argv*/);
  62. static bool_t    reply_proc(/*void *res, struct sockaddr_in *who*/);
  63. static void    brdcst(/*int argc, char **argv*/);
  64. static void    deletereg(/* int argc, char **argv */) ;
  65. static void    usage(/*void*/);
  66. static u_long    getprognum(/*char *arg*/);
  67. static u_long    getvers(/*char *arg*/);
  68. static void    get_inet_address(/*struct sockaddr_in *addr, char *host*/);
  69. extern u_long inet_addr();  /* in 4.2BSD, arpa/inet.h called that a in_addr */
  70. extern char *inet_ntoa();
  71.  
  72. /*
  73.  * Functions to be performed.
  74.  */
  75. #define    NONE        0    /* no function */
  76. #define    PMAPDUMP    1    /* dump portmapper registrations */
  77. #define    TCPPING        2    /* ping TCP service */
  78. #define    UDPPING        3    /* ping UDP service */
  79. #define    BRDCST        4    /* ping broadcast UDP service */
  80. #define DELETES        5    /* delete registration for the service */
  81.  
  82. int
  83. main(argc, argv)
  84.     int argc;
  85.     char **argv;
  86. {
  87.     register int c;
  88.     extern char *optarg;
  89.     extern int optind;
  90.     int errflg;
  91.     int function;
  92.     u_short portnum;
  93.  
  94.     function = NONE;
  95.     portnum = 0;
  96.     errflg = 0;
  97.     while ((c = getopt(argc, argv, "ptubdn:")) != EOF) {
  98.         switch (c) {
  99.  
  100.         case 'p':
  101.             if (function != NONE)
  102.                 errflg = 1;
  103.             else
  104.                 function = PMAPDUMP;
  105.             break;
  106.  
  107.         case 't':
  108.             if (function != NONE)
  109.                 errflg = 1;
  110.             else
  111.                 function = TCPPING;
  112.             break;
  113.  
  114.         case 'u':
  115.             if (function != NONE)
  116.                 errflg = 1;
  117.             else
  118.                 function = UDPPING;
  119.             break;
  120.  
  121.         case 'b':
  122.             if (function != NONE)
  123.                 errflg = 1;
  124.             else
  125.                 function = BRDCST;
  126.             break;
  127.  
  128.         case 'n':
  129.             portnum = (u_short) atoi(optarg);   /* hope we don't get bogus # */
  130.             break;
  131.  
  132.         case 'd':
  133.             if (function != NONE)
  134.                 errflg = 1;
  135.             else
  136.                 function = DELETES;
  137.             break;
  138.  
  139.         case '?':
  140.             errflg = 1;
  141.         }
  142.     }
  143.  
  144.     if (errflg || function == NONE) {
  145.         usage();
  146.         return (1);
  147.     }
  148.  
  149.     switch (function) {
  150.  
  151.     case PMAPDUMP:
  152.         if (portnum != 0) {
  153.             usage();
  154.             return (1);
  155.         }
  156.         pmapdump(argc - optind, argv + optind);
  157.         break;
  158.  
  159.     case UDPPING:
  160.         udpping(portnum, argc - optind, argv + optind);
  161.         break;
  162.  
  163.     case TCPPING:
  164.         tcpping(portnum, argc - optind, argv + optind);
  165.         break;
  166.  
  167.     case BRDCST:
  168.         if (portnum != 0) {
  169.             usage();
  170.             return (1);
  171.         }
  172.         brdcst(argc - optind, argv + optind);
  173.         break;
  174.  
  175.     case DELETES:
  176.         deletereg(argc - optind, argv + optind);
  177.         break;
  178.     }
  179.  
  180.     return (0);
  181. }
  182.         
  183. static void
  184. udpping(portnum, argc, argv)
  185.     u_short portnum;
  186.     int argc;
  187.     char **argv;
  188. {
  189.     struct timeval to;
  190.     struct sockaddr_in addr;
  191.     enum clnt_stat rpc_stat;
  192.     CLIENT *client;
  193.     u_long prognum, vers, minvers, maxvers;
  194.     int sock = RPC_ANYSOCK;
  195.     struct rpc_err rpcerr;
  196.     int failure;
  197.     
  198.     if (argc < 2 || argc > 3) {
  199.         usage();
  200.         exit(1);
  201.     }
  202.     prognum = getprognum(argv[1]);
  203.     get_inet_address(&addr, argv[0]);
  204.     /* Open the socket here so it will survive calls to clnt_destroy */
  205.     sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  206.     if (sock < 0) {
  207.         perror("rpcinfo: socket");
  208.         exit(1);
  209.     }
  210.     failure = 0;
  211.     if (argc == 2) {
  212.         /*
  213.          * A call to version 0 should fail with a program/version
  214.          * mismatch, and give us the range of versions supported.
  215.          */
  216.         addr.sin_port = htons(portnum);
  217.         to.tv_sec = 5;
  218.         to.tv_usec = 0;
  219.         if ((client = clntudp_create(&addr, prognum, (u_long)0,
  220.             to, &sock)) == NULL) {
  221.             clnt_pcreateerror("rpcinfo");
  222.             printf("program %lu is not available\n",
  223.                 prognum);
  224.             exit(1);
  225.         }
  226.         to.tv_sec = 10;
  227.         to.tv_usec = 0;
  228.         rpc_stat = clnt_call(client, NULLPROC, xdr_void, (char *)NULL,
  229.             xdr_void, (char *)NULL, to);
  230.         if (rpc_stat == RPC_PROGVERSMISMATCH) {
  231.             clnt_geterr(client, &rpcerr);
  232.             minvers = rpcerr.re_vers.low;
  233.             maxvers = rpcerr.re_vers.high;
  234.         } else if (rpc_stat == RPC_SUCCESS) {
  235.             /*
  236.              * Oh dear, it DOES support version 0.
  237.              * Let's try version MAX_VERS.
  238.              */
  239.             addr.sin_port = htons(portnum);
  240.             to.tv_sec = 5;
  241.             to.tv_usec = 0;
  242.             if ((client = clntudp_create(&addr, prognum, MAX_VERS,
  243.                 to, &sock)) == NULL) {
  244.                 clnt_pcreateerror("rpcinfo");
  245.                 printf("program %lu version %lu is not available\n",
  246.                     prognum, MAX_VERS);
  247.                 exit(1);
  248.             }
  249.             to.tv_sec = 10;
  250.             to.tv_usec = 0;
  251.             rpc_stat = clnt_call(client, NULLPROC, xdr_void,
  252.                 (char *)NULL, xdr_void, (char *)NULL, to);
  253.             if (rpc_stat == RPC_PROGVERSMISMATCH) {
  254.                 clnt_geterr(client, &rpcerr);
  255.                 minvers = rpcerr.re_vers.low;
  256.                 maxvers = rpcerr.re_vers.high;
  257.             } else if (rpc_stat == RPC_SUCCESS) {
  258.                 /*
  259.                  * It also supports version MAX_VERS.
  260.                  * Looks like we have a wise guy.
  261.                  * OK, we give them information on all
  262.                  * 4 billion versions they support...
  263.                  */
  264.                 minvers = 0;
  265.                 maxvers = MAX_VERS;
  266.             } else {
  267.                 (void) pstatus(client, prognum, MAX_VERS);
  268.                 exit(1);
  269.             }
  270.         } else {
  271.             (void) pstatus(client, prognum, (u_long)0);
  272.             exit(1);
  273.         }
  274.         clnt_destroy(client);
  275.         for (vers = minvers; vers <= maxvers; vers++) {
  276.             addr.sin_port = htons(portnum);
  277.             to.tv_sec = 5;
  278.             to.tv_usec = 0;
  279.             if ((client = clntudp_create(&addr, prognum, vers,
  280.                 to, &sock)) == NULL) {
  281.                 clnt_pcreateerror("rpcinfo");
  282.                 printf("program %lu version %lu is not available\n",
  283.                     prognum, vers);
  284.                 exit(1);
  285.             }
  286.             to.tv_sec = 10;
  287.             to.tv_usec = 0;
  288.             rpc_stat = clnt_call(client, NULLPROC, xdr_void,
  289.                 (char *)NULL, xdr_void, (char *)NULL, to);
  290.             if (pstatus(client, prognum, vers) < 0)
  291.                 failure = 1;
  292.             clnt_destroy(client);
  293.         }
  294.     }
  295.     else {
  296.         vers = getvers(argv[2]);
  297.         addr.sin_port = htons(portnum);
  298.         to.tv_sec = 5;
  299.         to.tv_usec = 0;
  300.         if ((client = clntudp_create(&addr, prognum, vers,
  301.             to, &sock)) == NULL) {
  302.             clnt_pcreateerror("rpcinfo");
  303.             printf("program %lu version %lu is not available\n",
  304.                 prognum, vers);
  305.             exit(1);
  306.         }
  307.         to.tv_sec = 10;
  308.         to.tv_usec = 0;
  309.         rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL,
  310.             xdr_void, (char *)NULL, to);
  311.         if (pstatus(client, prognum, vers) < 0)
  312.             failure = 1;
  313.     }
  314.     (void) close(sock); /* Close it up again */
  315.     if (failure)
  316.         exit(1);
  317. }
  318.  
  319. static void
  320. tcpping(portnum, argc, argv)
  321.     u_short portnum;
  322.     int argc;
  323.     char **argv;
  324. {
  325.     struct timeval to;
  326.     struct sockaddr_in addr;
  327.     enum clnt_stat rpc_stat;
  328.     CLIENT *client;
  329.     u_long prognum, vers, minvers, maxvers;
  330.     int sock = RPC_ANYSOCK;
  331.     struct rpc_err rpcerr;
  332.     int failure;
  333.  
  334.     if (argc < 2 || argc > 3) {
  335.         usage();
  336.         exit(1);
  337.     }
  338.     prognum = getprognum(argv[1]);
  339.     get_inet_address(&addr, argv[0]);
  340.     failure = 0;
  341.     if (argc == 2) {
  342.         /*
  343.          * A call to version 0 should fail with a program/version
  344.          * mismatch, and give us the range of versions supported.
  345.          */
  346.         addr.sin_port = htons(portnum);
  347.         if ((client = clnttcp_create(&addr, prognum, MIN_VERS,
  348.             &sock, 0, 0)) == NULL) {
  349.             clnt_pcreateerror("rpcinfo");
  350.             printf("program %lu is not available\n",
  351.                 prognum);
  352.             exit(1);
  353.         }
  354.         to.tv_sec = 10;
  355.         to.tv_usec = 0;
  356.         rpc_stat = clnt_call(client, NULLPROC, xdr_void, (char *)NULL,
  357.             xdr_void, (char *)NULL, to);
  358.         if (rpc_stat == RPC_PROGVERSMISMATCH) {
  359.             clnt_geterr(client, &rpcerr);
  360.             minvers = rpcerr.re_vers.low;
  361.             maxvers = rpcerr.re_vers.high;
  362.         } else if (rpc_stat == RPC_SUCCESS) {
  363.             /*
  364.              * Oh dear, it DOES support version 0.
  365.              * Let's try version MAX_VERS.
  366.              */
  367.             addr.sin_port = htons(portnum);
  368.             if ((client = clnttcp_create(&addr, prognum, MAX_VERS,
  369.                 &sock, 0, 0)) == NULL) {
  370.                 clnt_pcreateerror("rpcinfo");
  371.                 printf("program %lu version %lu is not available\n",
  372.                     prognum, MAX_VERS);
  373.                 exit(1);
  374.             }
  375.             to.tv_sec = 10;
  376.             to.tv_usec = 0;
  377.             rpc_stat = clnt_call(client, NULLPROC, xdr_void,
  378.                 (char *)NULL, xdr_void, (char *)NULL, to);
  379.             if (rpc_stat == RPC_PROGVERSMISMATCH) {
  380.                 clnt_geterr(client, &rpcerr);
  381.                 minvers = rpcerr.re_vers.low;
  382.                 maxvers = rpcerr.re_vers.high;
  383.             } else if (rpc_stat == RPC_SUCCESS) {
  384.                 /*
  385.                  * It also supports version MAX_VERS.
  386.                  * Looks like we have a wise guy.
  387.                  * OK, we give them information on all
  388.                  * 4 billion versions they support...
  389.                  */
  390.                 minvers = 0;
  391.                 maxvers = MAX_VERS;
  392.             } else {
  393.                 (void) pstatus(client, prognum, MAX_VERS);
  394.                 exit(1);
  395.             }
  396.         } else {
  397.             (void) pstatus(client, prognum, MIN_VERS);
  398.             exit(1);
  399.         }
  400.         clnt_destroy(client);
  401.         (void) close(sock);
  402.         sock = RPC_ANYSOCK; /* Re-initialize it for later */
  403.         for (vers = minvers; vers <= maxvers; vers++) {
  404.             addr.sin_port = htons(portnum);
  405.             if ((client = clnttcp_create(&addr, prognum, vers,
  406.                 &sock, 0, 0)) == NULL) {
  407.                 clnt_pcreateerror("rpcinfo");
  408.                 printf("program %lu version %lu is not available\n",
  409.                     prognum, vers);
  410.                 exit(1);
  411.             }
  412.             to.tv_usec = 0;
  413.             to.tv_sec = 10;
  414.             rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL,
  415.                 xdr_void, (char *)NULL, to);
  416.             if (pstatus(client, prognum, vers) < 0)
  417.                 failure = 1;
  418.             clnt_destroy(client);
  419.             (void) close(sock);
  420.             sock = RPC_ANYSOCK;
  421.         }
  422.     }
  423.     else {
  424.         vers = getvers(argv[2]);
  425.         addr.sin_port = htons(portnum);
  426.         if ((client = clnttcp_create(&addr, prognum, vers, &sock,
  427.             0, 0)) == NULL) {
  428.             clnt_pcreateerror("rpcinfo");
  429.             printf("program %lu version %lu is not available\n",
  430.                 prognum, vers);
  431.             exit(1);
  432.         }
  433.         to.tv_usec = 0;
  434.         to.tv_sec = 10;
  435.         rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL,
  436.             xdr_void, (char *)NULL, to);
  437.         if (pstatus(client, prognum, vers) < 0)
  438.             failure = 1;
  439.     }
  440.     if (failure)
  441.         exit(1);
  442. }
  443.  
  444. /*
  445.  * This routine should take a pointer to an "rpc_err" structure, rather than
  446.  * a pointer to a CLIENT structure, but "clnt_perror" takes a pointer to
  447.  * a CLIENT structure rather than a pointer to an "rpc_err" structure.
  448.  * As such, we have to keep the CLIENT structure around in order to print
  449.  * a good error message.
  450.  */
  451. static int
  452. pstatus(client, prognum, vers)
  453.     register CLIENT *client;
  454.     u_long prognum;
  455.     u_long vers;
  456. {
  457.     struct rpc_err rpcerr;
  458.  
  459.     clnt_geterr(client, &rpcerr);
  460.     if (rpcerr.re_status != RPC_SUCCESS) {
  461.         clnt_perror(client, "rpcinfo");
  462.         printf("program %lu version %lu is not available\n",
  463.             prognum, vers);
  464.         return (-1);
  465.     } else {
  466.         printf("program %lu version %lu ready and waiting\n",
  467.             prognum, vers);
  468.         return (0);
  469.     }
  470. }
  471.  
  472. static void
  473. pmapdump(argc, argv)
  474.     int argc;
  475.     char **argv;
  476. {
  477.     struct sockaddr_in server_addr;
  478.     register struct hostent *hp;
  479.     struct pmaplist *head = NULL;
  480.     int socket = RPC_ANYSOCK;
  481.     struct timeval minutetimeout;
  482.     register CLIENT *client;
  483.     struct rpcent *rpc;
  484.     
  485.     if (argc > 1) {
  486.         usage();
  487.         exit(1);
  488.     }
  489.     if (argc == 1)
  490.         get_inet_address(&server_addr, argv[0]);
  491.     else {
  492.         bzero((char *)&server_addr, sizeof server_addr);
  493.         server_addr.sin_family = AF_INET;
  494.         if ((hp = gethostbyname("localhost")) != NULL)
  495.             bcopy(hp->h_addr, (caddr_t)&server_addr.sin_addr,
  496.                 hp->h_length);
  497.         else
  498.             server_addr.sin_addr.s_addr = inet_addr("0.0.0.0");
  499.     }
  500.     minutetimeout.tv_sec = 60;
  501.     minutetimeout.tv_usec = 0;
  502.     server_addr.sin_port = htons(PMAPPORT);
  503.     if ((client = clnttcp_create(&server_addr, PMAPPROG,
  504.         PMAPVERS, &socket, 50, 500)) == NULL) {
  505.         clnt_pcreateerror("rpcinfo: can't contact portmapper");
  506.         exit(1);
  507.     }
  508.     if (clnt_call(client, PMAPPROC_DUMP, xdr_void, NULL,
  509.         xdr_pmaplist, &head, minutetimeout) != RPC_SUCCESS) {
  510.         fprintf(stderr, "rpcinfo: can't contact portmapper: ");
  511.         clnt_perror(client, "rpcinfo");
  512.         exit(1);
  513.     }
  514.     if (head == NULL) {
  515.         printf("No remote programs registered.\n");
  516.     } else {
  517.         printf("   program vers proto   port\n");
  518.         for (; head != NULL; head = head->pml_next) {
  519.             printf("%10ld%5ld",
  520.                 head->pml_map.pm_prog,
  521.                 head->pml_map.pm_vers);
  522.             if (head->pml_map.pm_prot == IPPROTO_UDP)
  523.                 printf("%6s",  "udp");
  524.             else if (head->pml_map.pm_prot == IPPROTO_TCP)
  525.                 printf("%6s", "tcp");
  526.             else
  527.                 printf("%6ld",  head->pml_map.pm_prot);
  528.             printf("%7ld",  head->pml_map.pm_port);
  529.             rpc = getrpcbynumber(head->pml_map.pm_prog);
  530.             if (rpc)
  531.                 printf("  %s\n", rpc->r_name);
  532.             else
  533.                 printf("\n");
  534.         }
  535.     }
  536. }
  537.  
  538. /* 
  539.  * reply_proc collects replies from the broadcast. 
  540.  * to get a unique list of responses the output of rpcinfo should
  541.  * be piped through sort(1) and then uniq(1).
  542.  */
  543.  
  544. /*ARGSUSED*/
  545. static bool_t
  546. reply_proc(res, who)
  547.     void *res;        /* Nothing comes back */
  548.     struct sockaddr_in *who; /* Who sent us the reply */
  549. {
  550.     register struct hostent *hp;
  551.  
  552.     hp = gethostbyaddr((char *) &who->sin_addr, sizeof who->sin_addr,
  553.         AF_INET);
  554.     printf("%s %s\n", inet_ntoa(who->sin_addr),
  555.         (hp == NULL) ? "(unknown)" : hp->h_name);
  556.     return(FALSE);
  557. }
  558.  
  559. static void
  560. brdcst(argc, argv)
  561.     int argc;
  562.     char **argv;
  563. {
  564.     enum clnt_stat rpc_stat;
  565.     u_long prognum, vers;
  566.  
  567.     if (argc != 2) {
  568.         usage();
  569.         exit(1);
  570.     }
  571.     prognum = getprognum(argv[0]);
  572.     vers = getvers(argv[1]);
  573.     rpc_stat = clnt_broadcast(prognum, vers, NULLPROC, xdr_void,
  574.         (char *)NULL, xdr_void, (char *)NULL, reply_proc);
  575.     if ((rpc_stat != RPC_SUCCESS) && (rpc_stat != RPC_TIMEDOUT)) {
  576.         fprintf(stderr, "rpcinfo: broadcast failed: %s\n",
  577.             clnt_sperrno(rpc_stat));
  578.         exit(1);
  579.     }
  580.     exit(0);
  581. }
  582.  
  583. static void
  584. deletereg(argc, argv)
  585.     int argc;
  586.     char **argv;
  587. {    u_long prog_num, version_num ;
  588.  
  589.     if (argc != 2) {
  590.         usage() ;
  591.         exit(1) ;
  592.     }
  593.     if (getuid()) { /* This command allowed only to root */
  594.         fprintf(stderr, "Sorry. You are not root\n") ;
  595.         exit(1) ;
  596.     }
  597.     prog_num = getprognum(argv[0]);
  598.     version_num = getvers(argv[1]);
  599.     if ((pmap_unset(prog_num, version_num)) == 0) {
  600.         fprintf(stderr, "rpcinfo: Could not delete registration for prog %s version %s\n",
  601.             argv[0], argv[1]) ;
  602.         exit(1) ;
  603.     }
  604. }
  605.  
  606. static void
  607. usage()
  608. {
  609.     fprintf(stderr, "Usage: rpcinfo [ -n portnum ] -u host prognum [ versnum ]\n");
  610.     fprintf(stderr, "       rpcinfo [ -n portnum ] -t host prognum [ versnum ]\n");
  611.     fprintf(stderr, "       rpcinfo -p [ host ]\n");
  612.     fprintf(stderr, "       rpcinfo -b prognum versnum\n");
  613.     fprintf(stderr, "       rpcinfo -d prognum versnum\n") ;
  614. }
  615.  
  616. static u_long
  617. getprognum(arg)
  618.     char *arg;
  619. {
  620.     register struct rpcent *rpc;
  621.     register u_long prognum;
  622.  
  623.     if (isalpha(*arg)) {
  624.         rpc = getrpcbyname(arg);
  625.         if (rpc == NULL) {
  626.             fprintf(stderr, "rpcinfo: %s is unknown service\n",
  627.                 arg);
  628.             exit(1);
  629.         }
  630.         prognum = rpc->r_number;
  631.     } else {
  632.         prognum = (u_long) atoi(arg);
  633.     }
  634.  
  635.     return (prognum);
  636. }
  637.  
  638. static u_long
  639. getvers(arg)
  640.     char *arg;
  641. {
  642.     register u_long vers;
  643.  
  644.     vers = (int) atoi(arg);
  645.     return (vers);
  646. }
  647.  
  648. static void
  649. get_inet_address(addr, host)
  650.     struct sockaddr_in *addr;
  651.     char *host;
  652. {
  653.     register struct hostent *hp;
  654.  
  655.     bzero((char *)addr, sizeof *addr);
  656.     addr->sin_addr.s_addr = (u_long) inet_addr(host);
  657.     if (addr->sin_addr.s_addr == -1 || addr->sin_addr.s_addr == 0) {
  658.         if ((hp = gethostbyname(host)) == NULL) {
  659.             fprintf(stderr, "rpcinfo: %s is unknown host\n", host);
  660.             exit(1);
  661.         }
  662.         bcopy(hp->h_addr, (char *)&addr->sin_addr, hp->h_length);
  663.     }
  664.     addr->sin_family = AF_INET;
  665. }
  666.